
import base64
import datetime
from hashlib import md5
from io import BytesIO
import math
import random
from captcha.image import ImageCaptcha
from app import myApp
from app.utils.RedisUtils import RedisUtil

alpha="abcdefghijklmnopqrstuvwxyz"
upperAlpha=str.upper(alpha)
number="0123456789"
operator="+-x"

config=myApp.config["captcha"]

class CaptchaUtils:
    captchaImage:BytesIO
    # 0 字母+数字  1 字母 2 算数  3 纯数字
    captchaType=0
    # 区分大小写
    isCase=False
    # 验证码的答案
    result=""
    width=0
    height=0
    length=0
    key=""
    expirSec=""

    def __init__(self) -> None:
        self.width=config["width"]
        self.height=config["height"]
        self.captchaType=config["type"]
        self.length=config["length"]
        self.isCase=config["isCase"]
        self.expirSec=config["expirSec"]
        timeMd5=md5(str(datetime.datetime.now().timestamp()).encode()).hexdigest()
        self.key="captcha_"+ "".join(random.choices(alpha+upperAlpha+number,k=10))+timeMd5

    def generate(self):
        code=self.getCode()
        self.captchaImage=ImageCaptcha().generate(code)
        return self
    
    def setLength(self,length):
        self.length=length
        return self
    
    def setCaptchaType(self,captchaType):
        self.captchaType=captchaType
        return self

    def getCode(self,captchaType=None):
        if captchaType!=None:
            self.captchaType=captchaType
        
        code=""
        if self.captchaType==0:
            code=random.choices(alpha+upperAlpha+number,k=self.length)
        elif self.captchaType==1:
            code=random.choices(alpha+upperAlpha,k=self.length)
        elif self.captchaType==2:
            nums=random.choices(number,k=2)
            oper=random.choices(operator,k=1)
            code=nums[0]+oper[0]+nums[1]+"="
            self.result=self.getCalculateResult(nums,oper[0])
        elif self.captchaType==3:
            code=math.floor(random.random() * math.pow(10,self.length))
            if(len(str(code))<self.length):
                code='0'+str(code)
            else:
                code=str(code)
        if self.captchaType==0 or self.captchaType==1:
            if self.isCase==False:
                code=str.lower("".join(code))
        self.result=code
        return code
    def toBase64(self):
        return base64.b64encode(self.captchaImage.getvalue()).decode("utf-8")
    
    def toBase64Browser(self):
        return "data:image/jpeg;base64,"+self.toBase64()

    def cache(self):
        if myApp.redis is None:
            return 
        myApp.redis.set(self.key,self.result,self.expirSec)
        return self

    def getCalculateResult(self,nums:list,oper:str):
        num1=int(nums[0])
        num2=int(nums[1])
        if oper=="+":
            result=num1+num2
        elif oper=="-":
            result=num1-num2
        elif oper=="x":
            result=num1*num2
        return result

    @staticmethod
    def verify(captchaKey,captchaValue):
        result=myApp.redis.get(captchaKey)
        if result==None:
            return False
        reponse=result.decode('utf-8')
        success=captchaValue==reponse
        # 验证码验证成功，删除缓存
        if success:
            myApp.redis.delete(captchaKey)
        return success
    

